package design;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
import javax.swing.JMenuBar;
import javax.swing.JCheckBox;
import javax.swing.JButton;
import java.awt.Font;

public class GraphicalUserInterface extends JFrame
{

	/**
	 * 
	 */
	private static final long serialVersionUID = -7452325698630740571L;

	private static final Font font = new Font("Arial", Font.PLAIN, 11);
	private static final String[] transitions =
	{ "a", "b", "c", "d", "e", "f" };
	private static final String[] variables =
	{ "V", "W", "X", "Y", "Z" };

	private JPanel contentPane;
	private JFileChooser fileChooser;
	private
	File file;
	private boolean deterministic;
	private boolean withVariables;
	private JTextArea textArea;
	private JMenuBar menuBar;
	private JToggleButton toggleVariables;
	private JToggleButton toggleEvents;
	private boolean[] transitionTypes = new boolean[transitions.length];
	private int[] domainFrom = new int[variables.length];
	private int[] domainTo = new int[variables.length];
	private int transitionsCount = 0;
	private int variableCount = 0;
	private JButton transitionNext;
	private JButton variableNext;
	private JLabel transitionLbl;
	private JLabel variableLbl;
	private JCheckBox transitionChBox;
	private JButton backButton;
	private JTextField varFrom;
	private JTextField varTo;
	private JButton done;
	private boolean doneVariables;
	private boolean doneTransitions;
	private JCheckBox chBoxWithVariables;
	private String restriction;

	public boolean isDeterministic()
	{
		return deterministic;
	}

	public void setDeterministic(boolean deterministic)
	{
		this.deterministic = deterministic;
	}

	public boolean isWithVariables()
	{
		return withVariables;
	}

	public void setWithVariables(boolean withVariables)
	{
		this.withVariables = withVariables;
	}

	public File getFile()
	{
		return file;
	}

	public void setFile(File file)
	{
		this.file = file;
	}

	/**
	 * Create the frame.
	 */
	public GraphicalUserInterface()
	{
		initializeDomain();
		doneVariables = true;
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(10, 10, 400, 500);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		menuBar = createMenuBar(0, 0, 400, 25);

		contentPane.add(menuBar);

		JCheckBox chBoxDeterministic = new JCheckBox("Deterministic");
		chBoxDeterministic.setFont(font);
		chBoxDeterministic.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				JCheckBox cBox = (JCheckBox) e.getSource();
				if (cBox.isSelected())
					deterministic = true;
				else
					deterministic = false;
			}
		});
		chBoxDeterministic.setBounds(18, 39, 129, 23);
		contentPane.add(chBoxDeterministic);

		chBoxWithVariables = new JCheckBox("With variables");
		chBoxWithVariables.setFont(font);
		chBoxWithVariables.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				JCheckBox cBox = (JCheckBox) e.getSource();
				if (cBox.isSelected())
				{
					withVariables = true;
					doneVariables = false;
					toggleVariables.setEnabled(true);
				}
				else
				{
					doneVariables = true;
					withVariables = false;
					toggleVariables.setSelected(false);
					varFrom.setVisible(false);
					varTo.setVisible(false);
					variableLbl.setVisible(false);
					variableNext.setVisible(false);
					if (!toggleEvents.isSelected())
						backButton.setVisible(false);
					toggleVariables.setEnabled(false);
				}
				contentPane.updateUI();
			}
		});
		chBoxWithVariables.setBounds(176, 39, 129, 23);
		contentPane.add(chBoxWithVariables);

		fileChooser = new JFileChooser();
		fileChooser.setDialogTitle("Choose a file");
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

		textArea = createTextArea(true, true);
		JScrollPane scrollPane = createJScrollPane(textArea, 22, 140, 278, 67);
		contentPane.add(scrollPane);

		JButton chooseFileBtn = new JButton("Choose file");
		chooseFileBtn.setFont(font);
		chooseFileBtn.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				int returnVal = fileChooser.showOpenDialog(GraphicalUserInterface.this);
				switch (returnVal)
				{
				case JFileChooser.APPROVE_OPTION:
					file = fileChooser.getSelectedFile();
					JOptionPane.showMessageDialog(contentPane, "File \"" + file.getAbsolutePath()
							+ "\" is selected.");
					break;
				case JFileChooser.ERROR_OPTION:
					JOptionPane.showMessageDialog(contentPane, "Error choosing file.");
					break;
				}
			}
		});
		chooseFileBtn.setBounds(22, 85, 125, 25);
		contentPane.add(chooseFileBtn);

		JButton createNewBtn = new JButton("Create new");
		createNewBtn.setFont(font);
		createNewBtn.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				try
				{
					Runtime.getRuntime().exec("java -jar JFLAP.jar");
				}
				catch (IOException ex)
				{
					System.err.println("IOException");
				}
			}
		});
		createNewBtn.setBounds(180, 85, 117, 25);
		contentPane.add(createNewBtn);

		backButton = new JButton("Back");
		backButton.setFont(font);
		backButton.setEnabled(false);
		backButton.setVisible(false);
		backButton.setBounds(22, 280, 60, 15);
		backButton.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				if (!transitionNext.isEnabled())
					transitionNext.setEnabled(true);
				if (!variableNext.isEnabled())
					variableNext.setEnabled(true);
				if (toggleEvents.isSelected())
				{
					if (transitionsCount > 0)
					{
						transitionsCount--;
						transitionChBox.setSelected(transitionTypes[transitionsCount]);
						transitionLbl.setText(transitions[transitionsCount]);
					}
					if (transitionsCount == 0)
						backButton.setEnabled(false);
				}
				if (toggleVariables.isSelected())
				{
					if (variableCount > 0)
					{
						variableCount--;
						varFrom.setText("" + domainFrom[variableCount]);
						varTo.setText("" + domainTo[variableCount]);
						variableLbl.setText(variables[variableCount]);
					}
					if (variableCount == 0)
						backButton.setEnabled(false);
				}
				contentPane.updateUI();
			}
		});
		contentPane.add(backButton);

		variableLbl = new JLabel();
		variableLbl.setVisible(false);
		variableLbl.setText(variables[0]);
		variableLbl.setFont(font);
		variableLbl.setBounds(128, 260, 50, 15);
		contentPane.add(variableLbl);

		varFrom = new JTextField();
		varFrom.setBounds(22, 260, 50, 15);
		varFrom.setVisible(false);
		varFrom.setFont(font);
		varFrom.setText("1");
		contentPane.add(varFrom);

		varTo = new JTextField();
		varTo.setBounds(75, 260, 50, 15);
		varTo.setVisible(false);
		varTo.setText("2");
		varTo.setFont(font);
		contentPane.add(varTo);

		variableNext = new JButton("Set");
		variableNext.setFont(font);
		variableNext.setVisible(false);
		variableNext.setBounds(84, 280, 60, 15);
		variableNext.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				if (isValidDomain(varFrom.getText(), varTo.getText()))
				{
					variableCount++;
					domainFrom[variableCount - 1] = Integer.parseInt(varFrom.getText());
					domainTo[variableCount - 1] = Integer.parseInt(varTo.getText());
					if (variableCount < variables.length)
					{
						variableLbl.setText(variables[variableCount]);
						varFrom.setText("" + domainFrom[variableCount]);
						varTo.setText("" + domainTo[variableCount]);
					}
					else
					{
						variableNext.setEnabled(false);
						doneVariables = true;
						variableCount--;
					}
					if (variableCount > 0)
						backButton.setEnabled(true);
				}
				else
				{
					JOptionPane.showMessageDialog(contentPane, "InvalidDomain!");
				}
				contentPane.updateUI();
			}
		});
		contentPane.add(variableNext);

		transitionLbl = new JLabel();
		transitionLbl.setFont(font);
		transitionLbl.setBounds(125, 260, 50, 15);
		transitionLbl.setVisible(false);
		contentPane.add(transitionLbl);
		transitionChBox = new JCheckBox("uncontrollable");
		transitionChBox.setFont(font);
		transitionChBox.setVisible(false);
		transitionChBox.setBounds(18, 260, 100, 15);
		contentPane.add(transitionChBox);

		transitionNext = new JButton("Set");
		transitionNext.setFont(font);
		transitionNext.setBounds(84, 280, 60, 15);
		transitionNext.setVisible(false);
		transitionNext.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				transitionsCount++;
				transitionTypes[transitionsCount - 1] = transitionChBox.isSelected();
				if (transitionsCount < transitions.length)
				{
					transitionChBox.setSelected(transitionTypes[transitionsCount]);
					transitionLbl.setText(transitions[transitionsCount]);
				}
				else
				{
					transitionNext.setEnabled(false);
					doneTransitions = true;
					transitionsCount--;
				}
				if (transitionsCount > 0)
					backButton.setEnabled(true);
				contentPane.updateUI();
			}
		});
		contentPane.add(transitionNext);

		// TOGGLE VARIABLES
		toggleVariables = new JToggleButton("Variables");
		toggleVariables.setFont(font);
		toggleVariables.setEnabled(false);
		toggleVariables.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				variableCount = 0;
				if (((JToggleButton) e.getSource()).isSelected())
				{
					if (toggleEvents.isSelected() == true)
					{
						transitionLbl.setVisible(false);
						transitionChBox.setVisible(false);
						transitionNext.setVisible(false);
						toggleEvents.setSelected(false);
					}
					variableNext.setEnabled(true);
					variableNext.setVisible(true);
					variableLbl.setVisible(true);
					variableLbl.setText(variables[variableCount]);
					varFrom.setVisible(true);
					varTo.setVisible(true);
					backButton.setVisible(true);
				}
				else
				{
					variableLbl.setVisible(false);
					variableNext.setVisible(false);
					varFrom.setVisible(false);
					varTo.setVisible(false);
					backButton.setVisible(false);
				}
				contentPane.updateUI();
			}
		});
		toggleVariables.setBounds(22, 232, 138, 15);
		contentPane.add(toggleVariables);

		// TOGGLE EVENTS
		toggleEvents = new JToggleButton("Transitions");
		toggleEvents.setFont(font);
		toggleEvents.setBounds(162, 232, 138, 15);
		toggleEvents.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				transitionsCount = 0;
				if (((JToggleButton) e.getSource()).isSelected())
				{
					if (toggleVariables.isSelected() == true)
					{
						variableLbl.setVisible(false);
						varFrom.setVisible(false);
						varTo.setVisible(false);
						variableNext.setVisible(false);
						toggleVariables.setSelected(false);
					}
					transitionLbl.setVisible(true);
					transitionLbl.setText(transitions[transitionsCount]);
					transitionChBox.setVisible(true);
					transitionNext.setEnabled(true);
					transitionNext.setVisible(true);
					backButton.setVisible(true);
				}
				else
				{
					transitionLbl.setVisible(false);
					transitionChBox.setVisible(false);
					transitionNext.setVisible(false);
					backButton.setVisible(false);
				}
				contentPane.updateUI();
			}
		});
		contentPane.add(toggleEvents);

		done = new JButton();
		done.setFont(font);
		done.setText("Done");
		done.setEnabled(true);
		done.setBounds(22, 300, 100, 30);
		done.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				if (doneTransitions && doneVariables)
				{
					StringBuilder sb = new StringBuilder();
					sb.append("Transitions: \n");
					for (int i = 0; i < transitionTypes.length; i++)
					{
						String state = transitionTypes[i] ? "uncontrollable" : "controllable";
						sb.append(transitions[i] + ": " + state + "\n");
					}
					if (chBoxWithVariables.isSelected())
					{
						sb.append("Variables: \n");
						for (int i = 0; i < domainFrom.length; i++)
							sb.append(variables[i] + ": [" + domainFrom[i] + ", " + domainTo[i]
									+ "]\n");
					}
					restriction = textArea.getText();
					sb.append(restriction);
					JOptionPane.showMessageDialog(contentPane, sb.toString());
				}
				else
					JOptionPane.showMessageDialog(contentPane,
							"Incomplete transition and/or variable data");
			}
		});
		contentPane.add(done);
	}

	public static boolean isValidDomain(String from, String to)
	{
		if (isValidInteger(from) && isValidInteger(to))
			return Integer.parseInt(from) > 0 && Integer.parseInt(from) < Integer.parseInt(to) ? true
					: false;
		return false;
	}

	public JMenuBar createMenuBar(int x, int y, int width, int height)
	{
		menuBar = new JMenuBar();
		menuBar.setBounds(x, y, width, height);
		JMenu fileMenu = createJMenu("File", KeyEvent.VK_F);
		JMenuItem fileMenuExitItem = new JMenuItem("Exit");
		fileMenuExitItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				System.exit(0);
			}
		});
		fileMenu.add(fileMenuExitItem);

		JMenu helpMenu = createJMenu("Help", KeyEvent.VK_H);
		JMenuItem helpMenuAboutItem = new JMenuItem("About");
		helpMenuAboutItem.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent event)
			{
				JOptionPane.showMessageDialog(contentPane, "version 1.2");
			}
		});
		helpMenu.add(helpMenuAboutItem);

		menuBar.add(fileMenu);
		menuBar.add(helpMenu);
		return menuBar;
	}

	public JMenu createJMenu(String text, int mnemonic)
	{
		JMenu menu = new JMenu(text);
		menu.setMnemonic(mnemonic);
		menu.addMouseListener(new MouseListener()
		{
			@Override
			public void mouseClicked(MouseEvent e)
			{
			}

			@Override
			public void mousePressed(MouseEvent e)
			{
			}

			@Override
			public void mouseReleased(MouseEvent e)
			{
			}

			@Override
			public void mouseEntered(MouseEvent e)
			{
				((JMenu) e.getSource()).setArmed(true);
			}

			@Override
			public void mouseExited(MouseEvent e)
			{
				((JMenu) e.getSource()).setArmed(false);
			}
		});
		return menu;
	}

	public JTextArea createTextArea(boolean editable, boolean lineWrap)
	{
		JTextArea textArea = new JTextArea();
		textArea.setEditable(editable);
		textArea.setLineWrap(lineWrap);

		return textArea;
	}

	public JScrollPane createJScrollPane(JTextArea textArea, int x, int y, int width, int heigth)
	{
		JScrollPane scrollPane = new JScrollPane(textArea);
		scrollPane.setBounds(x, y, width, heigth);
		return scrollPane;
	}

	public static boolean isValidInteger(String s)
	{
		try
		{
			Integer.parseInt(s);
			return true;
		}
		catch (NumberFormatException e)
		{
			return false;
		}
	}

	public void initializeDomain()
	{
		for (int i = 0; i < domainFrom.length; i++)
		{
			domainFrom[i] = 1;
			domainTo[i] = 2;
		}
	}

	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				try
				{
					GraphicalUserInterface frame = new GraphicalUserInterface();
					frame.setVisible(true);
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		});
	}
}
